package com.woniuxy.userapp.service.impl;


import cn.hutool.Hutool;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nimbusds.jose.JWSObject;
import com.woniuxy.authapp.client.AuthClient;
import com.woniuxy.authapp.client.param.Oauth2TokenInfo;
import com.woniuxy.commons.util.Result;
import com.woniuxy.commons.util.WebUtil;
import com.woniuxy.userapp.client.param.*;
import com.woniuxy.userapp.common.exception.Myexception.UserException;
import com.woniuxy.userapp.common.exception.code.UserExceptionCode;
import com.woniuxy.userapp.infra.model.mapper.FrontAccountMapper;
import com.woniuxy.userapp.infra.model.mapper.model.*;
import com.woniuxy.userapp.infra.model.mapper.model.dto.GetRoleListDto;
import com.woniuxy.userapp.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.userapp.service.constant.AuthConstant;
import com.woniuxy.userapp.service.dto.ChangeAccountMoneyDto;
import com.woniuxy.userapp.service.dto.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.HttpRequestMethodNotSupportedException;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2022-08-03
 */
@Service
public class FrontAccountServiceImpl extends ServiceImpl<FrontAccountMapper, FrontAccount> implements FrontAccountService {

    @Autowired
    private StudentService studentService;
    @Autowired
    private CoachService coachService;
    @Autowired
    private VenueService venueService;
    @Autowired
    private FaccountRoleService faccountRoleService;
    @Autowired
    private AuthClient authClient;


    @Override
    public UserDto loadUserByUsername(String userName) {
        //根据用户名获取当前用户对象
        FrontAccount frontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("user_name", userName));
        //前置判断
        if (frontAccount == null) throw new UserException(UserExceptionCode.ACCOUNT_NOT_EXISTS);
        //有此对象
        //根据对象获取其角色集合
        List<GetRoleListDto> roleList = getRoleList(frontAccount.getId());
        if(roleList.size() <=0 || roleList == null) throw new UserException(UserExceptionCode.ACCOUNT_NOT_ROLE);
        UserDto userDto = new UserDto();
        BeanUtil.copyProperties(frontAccount,userDto);
        //将权限集合放入userdto中
        userDto.setClientId("portal-app");
        List<String> stringStream = roleList.stream().map(item -> item.getId() + "_" + item.getRoleName()).collect(Collectors.toList());
        userDto.setRoles(stringStream);
        return userDto;
    }

    //根据id获取角色权限集合,前台不做权限
    public List<GetRoleListDto> getRoleList(Integer id){

//        String token = WebUtil.getRequest().getHeader("Authorization");
//        String realtoken = token.replace("Bearer " , "");
//        JWSObject jwsObject = JWSObject.parse(realtoken);
//        String userStr = jwsObject.getPayload().toString();
//        JSONObject entries = new JSONObject(userStr);
//        entries.getStr("")


        List<GetRoleListDto> roleList = baseMapper.getRoleList(id);
        return roleList;
    }

    /**
     * 根据id,余额,修改此账户余额
     *
     * @param changeAccountMoneyInfo
     */
    @Override
    public void changeMoney(ChangeAccountMoneyInfo changeAccountMoneyInfo) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        //付款方
        FrontAccount dudfrontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", changeAccountMoneyInfo.getDudId()));
        //收款方
        FrontAccount addfrontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", changeAccountMoneyInfo.getAddId()));
        //不存在该付款方
        if (dudfrontAccount == null) throw new UserException(UserExceptionCode.DEDACCOUNT_NOT_EXISTS);
        //不存在该收款方
        if (addfrontAccount == null) throw new UserException(UserExceptionCode.ADDACCOUNT_NOT_EXISTS);
        BigDecimal dudmoney = dudfrontAccount.getMoney();//付款方账户余额
        BigDecimal addmoney = addfrontAccount.getMoney();//收款方账户余额
        BigDecimal dudbalance = null;//剩下的余额
        BigDecimal addbalance = null;//剩下的余额
        if (!encoder.matches(changeAccountMoneyInfo.getDudpassword(), dudfrontAccount.getWalletPwd()))
            throw new UserException(UserExceptionCode.ACCOUNT_PAYWORD_ERROR);
        if (changeAccountMoneyInfo.getMoneyAmount().compareTo(dudmoney) == 1) {//用户余额小于课程余额
            throw new UserException(UserExceptionCode.ACCOUNT_NOT_MONEY);
        } else {
            //余额足够,扣款
             dudbalance = dudmoney.subtract(changeAccountMoneyInfo.getMoneyAmount());
             addbalance = addmoney.add(changeAccountMoneyInfo.getMoneyAmount());
        }
        baseMapper.update(null, new UpdateWrapper<FrontAccount>().set("money", dudbalance).eq("id", changeAccountMoneyInfo.getDudId()));
        baseMapper.update(null, new UpdateWrapper<FrontAccount>().set("money", addbalance).eq("id", changeAccountMoneyInfo.getAddId()));
    }

    /**
     * @param autoDeductMoneyInfo
     */
    @Override
    public void autoDeductMoney(AutoDeductMoneyInfo autoDeductMoneyInfo) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        //减款方
        FrontAccount dedFrontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", autoDeductMoneyInfo.getDeductionId()));
        //收款方
        FrontAccount addFrontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", autoDeductMoneyInfo.getAddId()));
        //前置判断
        if (dedFrontAccount == null) throw new UserException(UserExceptionCode.DEDACCOUNT_NOT_EXISTS);
        if (addFrontAccount == null) throw new UserException(UserExceptionCode.ADDACCOUNT_NOT_EXISTS);

        BigDecimal dudMoney = dedFrontAccount.getMoney();//扣款方账户余额
        BigDecimal addMoney = addFrontAccount.getMoney();
        BigDecimal dudBalance = null;//扣款方剩下的余额
        BigDecimal addBalance = null;//收款方剩下的余额
        System.out.println(autoDeductMoneyInfo.getMoneyAmount().compareTo(dudMoney));
        if (autoDeductMoneyInfo.getMoneyAmount().compareTo(dudMoney) == 1) {//用户余额小于课程余额
            throw new UserException(UserExceptionCode.ACCOUNT_NOT_MONEY);
        } else {
            //余额足够
            dudBalance = dudMoney.subtract(autoDeductMoneyInfo.getMoneyAmount());//扣
            addBalance = addMoney.add(autoDeductMoneyInfo.getMoneyAmount());//加
        }
        baseMapper.update(null, new UpdateWrapper<FrontAccount>().set("money", dudBalance).eq("id", autoDeductMoneyInfo.getDeductionId()));
        baseMapper.update(null, new UpdateWrapper<FrontAccount>().set("money", addBalance).eq("id", autoDeductMoneyInfo.getAddId()));
    }

    /**
     * 前台注册
     *
     * @param registerInfo
     */
    @Override
    public void register(RegisterInfo registerInfo) {
//        if(StrUtil.isEmpty(registerInfo.getUsername())|| StrUtil.isEmpty(registerInfo.getPassword()) ||
//        registerInfo.getNumber() == null) throw new
        //不存在该角色
        if(registerInfo.getNumber() != 1 && registerInfo.getNumber() != 2 && registerInfo.getNumber() != 3){
            throw new UserException(UserExceptionCode.ROLE_NOT_EXISTS);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        FrontAccount frontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("user_name", registerInfo.getUsername()));
        //账户已存在
        if (frontAccount != null) throw new UserException(UserExceptionCode.ADDACCOUNT_HAS_EXISTS);
        FrontAccount account = new FrontAccount();
        account.setUserName(registerInfo.getUsername());
        account.setPassword(encoder.encode(registerInfo.getPassword()));
        baseMapper.insert(account);//账户中插入一条数据


        //在对应的学生表,教练表,商家表增一条数据
        /**
         * 1:学生  场馆
         * 2:教练  教练
         * 3:商家  学生
         */
        if (registerInfo.getNumber() == 3) {
            Student student = new Student();
            student.setFrontAccountId(account.getId());
            student.setUserName(registerInfo.getUsername());
            student.setPassword(encoder.encode(registerInfo.getPassword()));
            studentService.save(student);
            FaccountRole faccountRole = new FaccountRole();
            faccountRole.setAccountId(account.getId());
            faccountRole.setRoleId(registerInfo.getNumber());
            faccountRoleService.save(faccountRole);
        } else if (registerInfo.getNumber() == 2) {
            Coach coach = new Coach();
            coach.setFrontAccountId(account.getId());
            coach.setUserName(registerInfo.getUsername());
            coach.setPassword(encoder.encode(registerInfo.getPassword()));
            coachService.save(coach);
            FaccountRole faccountRole = new FaccountRole();
            faccountRole.setAccountId(account.getId());
            faccountRole.setRoleId(registerInfo.getNumber());
            faccountRoleService.save(faccountRole);
        } else if (registerInfo.getNumber() == 1) {
            Venue venue = new Venue();
            venue.setFrontAccountId(account.getId());
            //场馆名字后续场馆自己改
            venue.setUserName(registerInfo.getUsername());
            venue.setPassword(encoder.encode(registerInfo.getPassword()));
            venueService.save(venue);
            FaccountRole faccountRole = new FaccountRole();
            faccountRole.setAccountId(account.getId());
            faccountRole.setRoleId(registerInfo.getNumber());
            faccountRoleService.save(faccountRole);
        }
    }

    @Override
    public Result<Oauth2TokenInfo> login(String username, String password) throws HttpRequestMethodNotSupportedException {
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password))
            throw new UserException(UserExceptionCode.USERNAME_OR_PASSWORD_NULL);
        Map<String, String> params = new HashMap<>();
        params.put("client_id", AuthConstant.PORTAL_CLIENT_ID);
        params.put("client_secret", "123456");
        params.put("grant_type", "password");
        params.put("username", username);
        params.put("password", password);
        Result<Oauth2TokenInfo> result = authClient.postAccessToken("password", AuthConstant.PORTAL_CLIENT_ID, "123456", null, username, password);
        return result;
    }

    @Override
    public void deposit(DepositInfo depositInfo) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        FrontAccount frontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", depositInfo.getAccountId()));
        //不存在该账户
        if(frontAccount == null) throw new UserException(UserExceptionCode.ACCOUNT_NOT_EXISTS);
        //支付密码错误
        if(!encoder.matches(depositInfo.getPassword(),frontAccount.getWalletPwd())) throw new UserException(UserExceptionCode.ACCOUNT_PAYWORD_ERROR);
        //提现余额大于余额
        if(frontAccount.getMoney().compareTo(depositInfo.getAmount()) == -1) throw new UserException(UserExceptionCode.DEPOSIT_ERROR);
        BigDecimal balance = frontAccount.getMoney().subtract(depositInfo.getAmount());
        baseMapper.update(null,new UpdateWrapper<FrontAccount>().set("money",balance).eq("id",depositInfo.getAccountId()));
    }

    @Override
    public void recharge(RechargeInfo rechargeInfo) {
        FrontAccount frontAccount = baseMapper.selectOne(new QueryWrapper<FrontAccount>().eq("id", rechargeInfo.getAccountId()));
        //不存在该账户
        if(frontAccount == null) throw new UserException(UserExceptionCode.ACCOUNT_NOT_EXISTS);
        BigDecimal balance = frontAccount.getMoney().add(rechargeInfo.getAmount());
        baseMapper.update(null,new UpdateWrapper<FrontAccount>().set("money",balance).eq("id",rechargeInfo.getAccountId()));
    }
}
